//------------------------------------------------------------------------------
// <copyright file="WinRtSocketListener.cpp" company="Microsoft">
//     Copyright (c) Microsoft Corporation.  All rights reserved.
// </copyright>
//------------------------------------------------------------------------------

#include "stdafx.h"

#ifndef USE_RAPIDJSON

#include "WinRtSocketListener.h"

using namespace Windows::Networking::Sockets;
using namespace Microsoft::Internal::GamesTest::Rpc::Server;

WinRtSocketListener::WinRtSocketListener()
	: m_systemSocketListener(nullptr)
{
}

GAMESTEST_ANNOTATE_HRESULT_METHOD HRESULT WinRtSocketListener::StartImpl(int port)
{
	HRESULT hr = S_OK;
	try
	{
		// Make sure port is valid before connecting
		if (port < 1 || port > 65535)
		{
			return E_INVALIDARG;
		}

		m_systemSocketListener = ref new StreamSocketListener();
		auto onSocketConnected = std::bind(&WinRtSocketListener::OnWinRtSocketConnected, this, std::placeholders::_1, std::placeholders::_2);
		m_socketConnectedToken = m_systemSocketListener->ConnectionReceived += ref new TypedEventHandler<StreamSocketListener^, StreamSocketListenerConnectionReceivedEventArgs^>(onSocketConnected);

		// If this code happens to be running on an STA thread, then we can't call task.wait() because
		// an exception will be thrown.  We're ok with that for now.
		wchar_t portToStringConversionBuffer[32];
		ZeroMemory(portToStringConversionBuffer, sizeof(portToStringConversionBuffer));
		_itow_s<32>(port, portToStringConversionBuffer, 10);

		Platform::String^ portAsString = ref new Platform::String(static_cast<const wchar_t*>(portToStringConversionBuffer));

		BindEndpoint(portAsString);
	}
	catch(Platform::COMException^ ex)
	{
		hr = ex->HResult;
	}

	return hr;
}

GAMESTEST_ANNOTATE_HRESULT_METHOD HRESULT WinRtSocketListener::StopImpl()
{
	HRESULT hr = S_OK;

	try
	{
		// According to the docs, deleting the object is the proper way to close it.
		// http://msdn.microsoft.com/en-us/library/windows/apps/windows.networking.sockets.streamsocketlistener.close
		delete m_systemSocketListener;
		m_systemSocketListener = nullptr;
	}
	catch(Platform::COMException^ ex)
	{
		hr = ex->HResult;
	}

	return hr;
}

void WinRtSocketListener::OnWinRtSocketConnected(StreamSocketListener^ sender, StreamSocketListenerConnectionReceivedEventArgs^ args)
{
	IRpcStringSocket* clientSocket = new WinRtStringSocket(args->Socket);
	this->OnSocketConnected(clientSocket);
}

void WinRtSocketListener::BindEndpoint(Platform::String^ port)
{
	create_task(m_systemSocketListener->BindEndpointAsync(nullptr, port)).wait();
}

#endif